// ExtractCallback.h

#ifndef __EXTRACT_CALLBACK_H
#define __EXTRACT_CALLBACK_H


#include "Common/String/ResourceString.h"

#include "Common/Agent/IFolderArchive.h"
#include "Common/Archive/ArchiveOpenCallback.h"

#ifndef _NO_CRYPTO
#include "Common/COM/IPassword.h"
#endif

#include "Common/FileSystem/IFolder.h"

#include "ProgressDialog2.h"

#ifdef LANG
#include "Common/Lang/LangUtils.h"
#endif

class ATL_NO_VTABLE CExtractCallbackImp :
	public CComObjectRootEx<CComSingleThreadModel>,
	public IExtractCallbackUI,
	public IOpenCallbackUI,
	//public IFolderArchiveExtractCallback, // mkultiple from IProgress
#ifndef _SFX
	public ICompressProgressInfo,
#endif
#ifndef _NO_CRYPTO
	public ICryptoGetTextPassword,
#endif
	public IFolderOperationsExtractCallback
{
public:

	BEGIN_COM_MAP(CExtractCallbackImp)
	COM_INTERFACE_ENTRY(IFolderOperationsExtractCallback)
	COM_INTERFACE_ENTRY(IFolderArchiveExtractCallback)
	COM_INTERFACE_ENTRY(IExtractCallbackUI)
	COM_INTERFACE_ENTRY(IOpenCallbackUI)
#ifndef _SFX
	COM_INTERFACE_ENTRY(ICompressProgressInfo)
#endif
#ifndef _NO_CRYPTO
	COM_INTERFACE_ENTRY(ICryptoGetTextPassword)
#endif
	COM_INTERFACE_ENTRY(IFolderOperationsExtractCallback)
	END_COM_MAP()

	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}

#ifndef _SFX
	STDMETHOD(SetRatioInfo)(const UINT64* inSize, const UINT64* outSize);
#endif

	//INTERFACE IProgress
	STDMETHOD(SetTotal)(UINT64 total);
	STDMETHOD(SetCompleted)(const UINT64* completeValue);

	//INTERFACE IOpenCallbackUI
	STDMETHOD(Open_CheckBreak)() ;
	STDMETHOD(Open_SetTotal)(const UINT64* files, const UINT64* bytes) ;
	STDMETHOD(Open_SetCompleted)(const UINT64* files, const UINT64* bytes) ;

	//INTERFACE IOpenCallbackUI_Crypto
	STDMETHOD(Open_CryptoGetTextPassword)(BSTR* password) ;
	STDMETHOD(Open_GetPasswordIfAny)(CString &password) ;
	virtual bool Open_WasPasswordAsked() ;
	virtual void Open_ClearPasswordWasAskedFlag() ;

	// IFolderArchiveExtractCallback
	// STDMETHOD(SetTotalFiles)(UINT64 total);
	// STDMETHOD(SetCompletedFiles)(const UINT64 *value);
	STDMETHOD(AskOverwrite)(
		const wchar_t* existName, const FILETIME* existTime, const UINT64* existSize,
		const wchar_t* newName, const FILETIME* newTime, const UINT64* newSize,
		Common::Archive::OverwriteAnswer* answer);
	STDMETHOD (PrepareOperation)(const wchar_t* name, bool isFolder, INT32 askExtractMode, const UINT64* position);

	STDMETHOD(MessageError)(const wchar_t* message);
	STDMETHOD(SetOperationResult)(INT32 operationResult, bool encrypted);

	// IExtractCallbackUI

	HRESULT BeforeOpen(const wchar_t* name);
	HRESULT OpenResult(const wchar_t* name, HRESULT result, bool encrypted);
	HRESULT ThereAreNoFiles();
	HRESULT ExtractResult(HRESULT result);

#ifndef _NO_CRYPTO
	HRESULT SetPassword(const CString &password);
#endif

	// IFolderOperationsExtractCallback
	STDMETHOD(AskWrite)(
		const wchar_t* srcPath,
		INT32 srcIsFolder,
		const FILETIME* srcTime,
		const UINT64* srcSize,
		const wchar_t* destPathRequest,
		BSTR* destPathResult,
		INT32* writeAnswer);
	STDMETHOD(ShowMessage)(const wchar_t* message);
	STDMETHOD(SetCurrentFilePath)(const wchar_t* filePath);
	STDMETHOD(SetNumFiles)(UINT64 numFiles);

	// ICryptoGetTextPassword
#ifndef _NO_CRYPTO
	STDMETHOD(CryptoGetTextPassword)(BSTR* password);
#endif

private:
	CString _currentArchivePath;
	bool _needWriteArchivePath;

	CString _currentFilePath;
	bool _isFolder;

	HRESULT SetCurrentFilePath2(const wchar_t* filePath);
	void AddErrorMessage(LPCWSTR message);
public:
	CProgressDialog2* ProgressDialog;
#ifndef _SFX
	UINT64 NumFolders;
	UINT64 NumFiles;
	bool NeedAddFile;
#endif
	UINT32 NumArchiveErrors;
	bool ThereAreMessageErrors;
	Common::Archive::Extract::OverwriteMode OverwriteMode;

#ifndef _NO_CRYPTO
	bool PasswordIsDefined;
	bool PasswordWasAsked;
	CString Password;
#endif

	CExtractCallbackImp():
#ifndef _NO_CRYPTO
		PasswordIsDefined(false),
		PasswordWasAsked(false),
#endif
		OverwriteMode(Common::Archive::Extract::OverwriteMode::kAskBefore)
	{}

	~CExtractCallbackImp();
	void Init();

	bool IsOK() const
	{
		return NumArchiveErrors == 0 && !ThereAreMessageErrors;
	}
};

#endif
